TITLE c3_context_x86.asm

; THIS ASM FILE IS ONLY FOR X86 (i386)

BLENGTH TEXTEQU <04h>

.386
.MODEL  flat, STDCALL

.DATA

;//////////////////////////////////////////////////////////////////////////////////

;

;//////////////////////////////////////////////////////////////////////////////////

.CODE

;//////////////////////////////////////////////////////////////////////////////////
; API declear
; Prevent MASM generate code like "push ebp, mov ebp, esp"

c3_restore_context PROC C
	jmp _inside_restore_context;
c3_restore_context ENDP

c3_jmp_context PROC C
	jmp _inside_jmp_context;
c3_jmp_context ENDP

c3_save_context PROC C
	jmp _inside_save_context;
c3_save_context ENDP

c3_get_call_bp PROC C
	jmp _inside_get_call_bp;
c3_get_call_bp ENDP

c3_set_jmp PROC C
	jmp _inside_set_jmp;
c3_set_jmp ENDP

c3_long_jmp PROC C
	jmp _inside_long_jmp;
c3_long_jmp ENDP

;//////////////////////////////////////////////////////////////////////////////////

_inside_set_jmp:

	mov		ecx,									[esp+BLENGTH];				GET ARGUMENT #1 (fast_context*)

	xor		eax,									eax;

	mov		[ecx+00h*BLENGTH],		ebx;
	mov		[ecx+01h*BLENGTH],		edi;
	mov		[ecx+02h*BLENGTH],		esi;

	mov		[ecx+07h*BLENGTH],		ebp;
	mov		[ecx+08h*BLENGTH],		esp;

	mov		edx,									[esp];
	mov		[ecx+09h*BLENGTH],		edx;

	ret;

;//////////////////////////////////////////////////////////////////////////////////

_inside_long_jmp:
	
	mov		ecx,									[esp+BLENGTH];						GET ARGUMENT #1 (fast_context*)
	mov		eax,									[esp+02h*BLENGTH];				GET ARGUMENT #2 (DWORD)

	mov		ebx,									[ecx+00h*BLENGTH];
	mov		edi,									[ecx+01h*BLENGTH];
	mov		esi,									[ecx+02h*BLENGTH];

	mov		ebp,									[ecx+07h*BLENGTH];
	mov		esp,									[ecx+08h*BLENGTH];

	mov		edx,									[ecx+09h*BLENGTH];

	mov		[esp],								edx;

	ret;

;//////////////////////////////////////////////////////////////////////////////////

_inside_restore_context:

	mov		ecx,									[esp+BLENGTH];				GET ARGUMENT #1 (context*)

	; mov	ebx,								[ecx+01h*BLENGTH];		RESTORE REGISTER
	mov		edi,									[ecx+02h*BLENGTH];
	mov		esi,									[ecx+03h*BLENGTH];

	mov		eax,									[ecx+0ah*BLENGTH];		GET STACK SIZE
	mov		ebx,									[ecx+09h*BLENGTH];		GET BP

	add		ecx,									0bh*BLENGTH;				LOAD STACK
	sub		ebx,									02h*BLENGTH;

_inside_restore_context_loop:
	and		eax,									eax;
	jz			_inside_restore_context_loop_end;

	mov		edx,									[ecx];
	mov		[ebx],								edx;

	add		ecx,									BLENGTH;
	sub		ebx,									BLENGTH;
	sub		eax,									BLENGTH;

	jmp		_inside_restore_context_loop;

_inside_restore_context_loop_end:

	mov		ebx,									[ecx+01h*BLENGTH];
	ret;

;//////////////////////////////////////////////////////////////////////////////////

_inside_jmp_context:

	mov		ecx,									[esp+BLENGTH];				GET ARGUMENT #1 (context*)
	mov		edx,									[ecx+00h*BLENGTH];

	and		edx,									edx;
	jz			_inside_jmp_context_end;

	mov		[esp],								edx;
	xor		eax,									eax;
	mov		[ecx+00h*BLENGTH],		eax;									CLEAR IP PLACE

_inside_jmp_context_end:

	ret;

;//////////////////////////////////////////////////////////////////////////////////

_inside_save_context:
	
	mov		ecx,									[esp+BLENGTH];				GET ARGUMENT #1 (context*)

	mov		edx,									[esp];								GET AND SAVE RETURN PLACE;
	mov		[ecx+00h*BLENGTH],		edx;
	
	mov		[ecx+01h*BLENGTH],		ebx;									SAVE REGISTER
	mov		[ecx+02h*BLENGTH],		edi;
	mov		[ecx+03h*BLENGTH],		esi;

	mov		ebx,									[ecx+09h*BLENGTH];		SAVE STACK SIZE
	sub		ebx,									esp;
	sub		ebx,									03h*BLENGTH;
	mov		[ecx+0ah*BLENGTH],		ebx;	
	mov		eax,									ebx;									

	mov		ebx,									[ecx+09h*BLENGTH];		GET BP

	add		ecx,									0bh*BLENGTH;				SAVE STACK
	sub		ebx,									02h*BLENGTH;					SIZE: AX  BP: BX		

_inside_save_context_loop:
	and		eax,									eax;
	jz			_inside_save_context_loop_end;

	mov		edx,									[ebx];
	mov		[ecx],								edx;

	add		ecx,									BLENGTH;
	sub		ebx,									BLENGTH;
	sub		eax,									BLENGTH;

	jmp		_inside_save_context_loop;

_inside_save_context_loop_end:
	mov		ebx,									[ecx+01h*BLENGTH];
	ret;

;//////////////////////////////////////////////////////////////////////////////////

_inside_get_call_bp:

	mov		eax,									esp;
	ret;

;//////////////////////////////////////////////////////////////////////////////////

END